import {
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  Injectable,
  OnDestroy,
  OnInit,
  Pipe,
  PipeTransform,
  ViewChild,
} from '@angular/core';
import { cloneDeep as _cloneDeep, filter as _filter, uniqueId as _uniqueId } from 'lodash';
import { Observable, of, Subject } from 'rxjs';
import { delay, startWith, takeUntil } from 'rxjs/operators';
import { DatatableComponent, FilterItem, MessageboxService, PaginatorComponent, TableFilterConfig, TagItem } from '@iux/live';

interface DemoUser {
  id: string;
  name: string;
  age: number;
  random: number;
  expand: boolean;
  disabled?: boolean;
}

@Injectable()
export class UserService {
  length = 400;
  users: DemoUser[];

  constructor() {
    this.users = this.initUser();
  }

  getUsers(data: { [key: string]: any }) {
    let { users } = this;
    let total = users.length;
    const { filters, sort, pageIndex, pageSize } = data,
      startIndex = pageIndex * pageSize,
      endIndex = (pageIndex + 1) * pageSize;

    // 模拟异步过滤
    if (filters?.length) {
      filters.forEach(filter => {
        if (filter.key === 'random') {
          users = _filter(users, item => filter.value.includes(item.random % 2 === 0) || !filter.value.length);
        }
        if (filter.key === 'age') {
          users = _filter(users, item => filter.value[0] == item.age);
        }
      });
      total = users.length;
    }
    if (sort?.key) {
      if (sort.direction === 'asc') {
        users = users.sort((a, b) => a[sort.key] - b[sort.key]);
      }
      if (sort.direction === 'desc') {
        users = users.sort((a, b) => b[sort.key] - a[sort.key]);
      }
    }

    users = users.slice(startIndex, endIndex);

    return of({ users, total }).pipe(delay(300));
  }

  initUser() {
    const users = Array.from({ length: this.length }).map((item, key) => ({
      id: _uniqueId('uid'),
      name: `user${key}`,
      age: 10 + key,
      expand: false,
      random: parseInt(`${Math.random() * 100}`, 10),
      disabled: key % 5 === 0,
      checkboxTip: key % 5 === 0 ? '当前数据不可选择' : '',
    }));
    return users;
  }
}

@Pipe({ name: 'selectable' })
export class SelectionPipe implements PipeTransform {
  transform(value: DemoUser[], exponent: string = 'disabled') {
    return _filter(value, item => !item[exponent]);
  }
}

@Component({
  selector: 'app-remote-load-data',
  templateUrl: './remote-load-data.component.html',
  styles: [
    `
      h3 {
        margin-bottom: 0.08rem;
      }
      lv-paginator {
        margin-top: 16px;
      }
    `,
  ],
  providers: [UserService],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class RemoteLoadDataComponent implements OnInit, OnDestroy {
  data: DemoUser[];
  selection: DemoUser[];

  pageSize = 10;
  pageIndex = 0;
  total: number;

  filtersMap: { [key: string]: any } = {};
  cacheFiltersMap: { [key: string]: any } = {};
  filterState: FilterItem[] = [];
  filterTags: TagItem[] = [];
  search$ = new Subject<string>();

  params: { [key: string]: any } = { pageIndex: this.pageIndex, pageSize: this.pageSize };
  params$ = new Subject<{ [key: string]: any }>();

  destroy$ = new Subject<void>();

  @ViewChild(DatatableComponent, { static: false }) lvTable: DatatableComponent;
  @ViewChild(PaginatorComponent, { static: false }) lvPaginator: PaginatorComponent;

  constructor(private service: UserService, private messageBox: MessageboxService, private cdr: ChangeDetectorRef) {}

  ngOnInit() {
    this.initAsyncData();
    this.setFilters();
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }

  initAsyncData() {
    this.params$.pipe(startWith(this.params), takeUntil(this.destroy$)).subscribe(res => {
      this.service.getUsers(res).subscribe((res: { users: DemoUser[]; total: number }) => {
        this.data = res.users;
        this.total = res.total;
        this.cdr.markForCheck();
      });
    });
  }

  filterChange(options: TableFilterConfig) {
    const { key, value } = options;
    if (key === 'age' && value?.includes('all')) {
      this.removeFilterState({ label: { key } });
      return;
    }

    this.lvTable.filter(options);
    this.lvPaginator.jumpToFisrtPage();
  }

  // 所有条件
  stateChange(source: { [key: string]: any }) {
    console.log('stateChange', source);

    let params: { [key: string]: any } = {};

    if (source.paginator) {
      params = { ...params, ...source.paginator };
    }

    if (source.filterState) {
      params = { ...params, filters: source.filterState };
    }

    if (source.sort) {
      params = { ...params, ...{ sort: source.sort } };
    }

    this.filterState = _filter(source.filterState, item => item.value && item.value.length);
    this.filterTags = this.filterState.map((item: TagItem) => ({ label: item, removable: true }));

    this.updateParams(params);
  }

  updateParams(data) {
    this.params$.next((this.params = { ...this.params, ...data }));
  }

  setFilters() {
    const ageFilters = [
        {
          key: -1,
          label: '全部',
          value: 'all',
        },
        {
          key: 0,
          label: '0',
          value: '0',
        },
        {
          key: 10,
          label: '10',
          value: '10',
        },
        {
          key: 20,
          label: '20',
          value: '20',
        },
        {
          key: 50,
          label: '50',
          value: '50',
        },
        {
          key: 100,
          label: '100',
          value: '100',
        },
      ],
      randomFilters = [
        {
          key: 0,
          label: 'odd',
          value: false,
          selected: false,
        },
        {
          key: 1,
          label: 'even',
          value: true,
          selected: false,
        },
      ];

    this.filtersMap.age = ageFilters;
    this.filtersMap.random = randomFilters;
    this.cacheFiltersMap = _cloneDeep(this.filtersMap);
  }

  beforeRemove = () =>
    new Observable(observer => {
      this.messageBox.confirm({
        lvHeader: 'Delete',
        lvContent: 'Are you sure you want to delete?',
        lvAfterClose: () => {
          observer.next(false);
          observer.complete();
        },
        lvOk: () => {
          observer.next(true);
        },
      });
    });

  removeFilterState(source) {
    const { key } = source.label;
    this.lvTable.removeFilter(key);
    this.filtersMap[key] = _cloneDeep(this.cacheFiltersMap[key]);
  }

  clearFilterState() {
    this.lvTable.removeFilter();
    this.lvPaginator.jumpToFisrtPage();
    this.setFilters();
  }

  selectionChange(source) {
    console.log('selection change', source);
  }

  goToLink(e: Event): void {
    e.preventDefault();
    const title = Array.from(document.querySelectorAll('.ui-anchor-link-title'));
    const target = title.filter(item => item.textContent.includes('表格默认过滤'))[0];
    target.dispatchEvent(new Event('click'));
  }
}
